﻿using EquipmentAlarmSystem.Service.Models;
using S7.Net;
using S7.Net.Types;

namespace EquipmentAlarmSystem.Service.EquipmentCommunicationUnit.Siemens;

public class S7(DeviceInformationSiemensS7 siemensS7) : ICommunication
{
    Plc plc;

    public bool Connected => plc.IsConnected;

    public DeviceInformation Information => siemensS7;

    public bool AlarmReading(out List<PointInformation> result, out bool isReconnection, out string content)
    {
        try
        {
            result = new();
            //检查连接
            if (plc.IsConnected)
            {
                //自动报警检查
                if (siemensS7.EnableAutomaticAlarm == true)
                {
                    try
                    {
                        //读取状态地址 
                        if ((bool)plc.Read(siemensS7.AutomaticAlarmAddr) == false)
                        {
                            result = null;
                            content = "设备未运行";
                            isReconnection = false;
                            return true;
                        }
                    }
                    catch (Exception ex)
                    {
                        content = ex.Message;
                        isReconnection = false;
                        return false;
                    }
                }
                Read(out List<PointInformation> value);
                foreach (var item in value)
                {
                    if (item.Value == true)
                    {
                        result.Add(item);
                    }
                }
                if (result.Count <= 0)
                {
                    result = null;
                }
                content = "成功";
                isReconnection = false;
                return true;
            }
            else
            {
                content = "设备未连接";
                isReconnection = true;
                return false;
            }
        }
        catch (Exception ex)
        {
            plc?.Close();
            result = null;
            content = ex.Message;
            isReconnection = false;
            return false;
        }
    }

    public void Close()
    {
        plc?.Close();
    }

    public void Open()
    {
        try
        {
            //检查地址有效性
            Library.ConnectionCheck connectionCheck = new();
            connectionCheck.IsIpEffective(siemensS7.Ip);
            //plc对象
            plc = new(siemensS7.CpuType, siemensS7.Ip, siemensS7.Port, siemensS7.Rack, siemensS7.Slot);
            //打开连接
            plc.Open();
        }
        catch (Exception ex)
        {
            plc?.Close();
            throw new Exception(ex.Message);
        }
    }

    //数据点位地址列表
    List<PointInformation> results = null;
    //分页数据采集
    private List<List<DataItem>> pages = null;
    public void Read(out List<PointInformation> result)
    {
        //检查报警地址是否存在 并过滤未启用报警数据
        if (results is null)
        {
            //数据地址检查
            if (siemensS7.PointInformation is null || siemensS7.PointInformation.Count < 1)
            {
                results = null;
                result = results;
                return;
            }
            results = new List<PointInformation>();
            //过滤未启用报警数据
            foreach (var item in siemensS7.PointInformation)
            {
                //未启用报警，则不添加
                if (item.IsEnabled == false)
                {
                    continue;
                }
                results.Add(item);
            }
        }
        //检测是否批量读取
        if (siemensS7.IsMultiple)
        {
            if (pages is null)
            {
                //获取数据地址
                List<DataItem> data = new List<DataItem>();
                //地址转换
                foreach (var item in results)
                {
                    data.Add(DataItem.FromAddress(item.Address));
                }
                // 将一维列表按长度分页   单纯最大数据量 16
                pages = Library.Basics.PaginateList(data, 16);
            }
            // 输出分页结果  
            foreach (var page in pages)
            {
                //批量读取
                plc.ReadMultipleVars(page);
                Thread.Sleep(5);
            }
            //列表转换
            List<DataItem> oneDimensionalList = pages.SelectMany(list => list).ToList();
            //遍历结果
            for (int i = 0; i < oneDimensionalList.Count; i++)
            {
                //是否需要验证地址对应关系？
                //...
                results[i].Value = (bool)oneDimensionalList[i].Value;
            }
        }
        else
        {
            foreach (var item in results)
            {
                item.Value = (bool)plc.Read(item.Address);
                Thread.Sleep(5);
            }
        }
        result = results;
    }
}
